package com.CST.service.impl.ys;

import com.CST.common.constant.Constants;
import com.CST.dto.ys.YsResultDTO;
import com.CST.entity.cb.BdSysUser;
import com.CST.entity.ys.YsDepartment;
import com.CST.entity.ys.YsSubject;
import com.CST.mapper.cst.cb.BdSysUserMapper;
import com.CST.mapper.cst.ys.YsBudgetResultsMapper;
import com.CST.service.ys.YsBudgetResultsService;
import com.CST.util.ExcelTransfer;
import com.CST.util.HttpUtil;
import com.CST.util.PageHelperTool;
import com.CST.vo.cb.ExcelHead;
import com.CST.vo.cb.ExcelVO;
import com.CST.vo.ys.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author qtx
 * @since 2023-05-28
 */
@Service
public class YsBudgetResultsServiceImpl extends ServiceImpl<YsBudgetResultsMapper, YsSubject> implements YsBudgetResultsService {

    private final ExcelTransfer<YsBudgetResultsVO> excelTransfer;
    private final ExcelTransfer<YsAllYearBudgetManageResultsVO> excelTransfer2;

    @Autowired
    private BdSysUserMapper userMapper;

    public YsBudgetResultsServiceImpl(ExcelTransfer<YsBudgetResultsVO> excelTransfer, ExcelTransfer<YsAllYearBudgetManageResultsVO> excelTransfer2) {
        this.excelTransfer = excelTransfer;
        this.excelTransfer2 = excelTransfer2;
    }

    @Override
    public PageInfo<YsBudgetResultsVO> listYsBusinessResults(YsResultDTO dto) {
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        //  todo  临时权限
        if (!"ALL".equals(user.getDeptCode())) {
            dto.setDepartmentCode(user.getDeptCode());
        }
        List<YsBudgetResultsVO> resultList = getBusinessYsBudgetResultsVOS(dto);
        PageInfo<YsBudgetResultsVO> page = PageHelperTool.excutePageInfo(resultList, dto.getNum(), dto.getSize());
        List<YsBudgetResultsVO> list = page.getList();
        YsBudgetResultsVO vo = new YsBudgetResultsVO();
        // 合计
        BigDecimal xSanTotal = resultList.stream().map(YsBudgetResultsVO::getXSan).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal xXuTotal = resultList.stream().map(YsBudgetResultsVO::getXXu).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal xAllTotal = resultList.stream().map(YsBudgetResultsVO::getXAll).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal zSanTotal = resultList.stream().map(YsBudgetResultsVO::getZSan).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal zXuTotal = resultList.stream().map(YsBudgetResultsVO::getZXu).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal zAllTotal = resultList.stream().map(YsBudgetResultsVO::getZAll).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 全年预算下达
        BigDecimal san134Total = resultList.stream().map(YsBudgetResultsVO::getSan134).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal xu134Total = resultList.stream().map(YsBudgetResultsVO::getXu134).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal all134Total = resultList.stream().map(YsBudgetResultsVO::getAll134).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 全年预算执行
        BigDecimal sanYearTotal = resultList.stream().map(YsBudgetResultsVO::getSanYear).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal xuYearTotal = resultList.stream().map(YsBudgetResultsVO::getXuYear).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal allYearTotal = resultList.stream().map(YsBudgetResultsVO::getAllYear).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 合计 当期执行率
        BigDecimal sanRate = zSanTotal.divide(xSanTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : xSanTotal, 4, RoundingMode.HALF_UP);
        BigDecimal xuRate = zXuTotal.divide(xXuTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : xXuTotal, 4, RoundingMode.HALF_UP);
        BigDecimal allRate = zAllTotal.divide(xAllTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : xAllTotal, 4, RoundingMode.HALF_UP);

        vo.setSanM(sanRate.multiply(new BigDecimal(100)));
        vo.setXuM(xuRate.multiply(new BigDecimal(100)));
        vo.setAllM(allRate.multiply(new BigDecimal(100)));

        if (xSanTotal.compareTo(BigDecimal.ZERO) == 0 && zSanTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setSanMFlag(1);
        } else {
            vo.setSanMFlag(0);
        }

        if (xXuTotal.compareTo(BigDecimal.ZERO) == 0 && zXuTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setXuMFlag(1);
        } else {
            vo.setXuMFlag(0);
        }

        if (xAllTotal.compareTo(BigDecimal.ZERO) == 0 && zAllTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setAllMFlag(1);
        } else {
            vo.setAllMFlag(0);
        }

        // 合计 预算总执行率
        BigDecimal sanYearRate = sanYearTotal.divide(san134Total.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : san134Total, 4, RoundingMode.HALF_UP);
        BigDecimal xuYearRate = xuYearTotal.divide(xu134Total.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : xu134Total, 4, RoundingMode.HALF_UP);
        BigDecimal allYearRate = allYearTotal.divide(all134Total.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : all134Total, 4, RoundingMode.HALF_UP);

        vo.setSanY(sanYearRate.multiply(new BigDecimal(100)));
        vo.setXuY(xuYearRate.multiply(new BigDecimal(100)));
        vo.setAllY(allYearRate.multiply(new BigDecimal(100)));

        if (san134Total.compareTo(BigDecimal.ZERO) == 0 && sanYearTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setSanYFlag(1);
        } else {
            vo.setSanYFlag(0);
        }

        if (xu134Total.compareTo(BigDecimal.ZERO) == 0 && xuYearTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setXuYFlag(1);
        } else {
            vo.setXuYFlag(0);
        }

        if (all134Total.compareTo(BigDecimal.ZERO) == 0 && allYearTotal.compareTo(BigDecimal.ZERO) > 0) {
            vo.setAllYFlag(1);
        } else {
            vo.setAllYFlag(0);
        }

        vo.setSubjectName("合计");
        vo.setXSan(xSanTotal);
        vo.setXXu(xXuTotal);
        vo.setXAll(xAllTotal);
        vo.setZSan(zSanTotal);
        vo.setZXu(zXuTotal);
        vo.setZAll(zAllTotal);
        list.add(vo);
        page.setList(list);
        return page;
    }

    @Override
    public void exportExcelYsBusinessResults(HttpServletResponse response, YsResultDTO dto) {
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        // todo  临时权限
        if (!"ALL".equals(user.getDeptCode())) {
            dto.setDepartmentCode(user.getDeptCode());
        }
        excelTransfer.exportExcel(response, getBusinessYsBudgetResultsVOS(dto), "部门预算执行结果", "sheet",
                YsBudgetResultsVO.class);
    }

    @Override
    public PageInfo<YsBudgetResultsVO> listYsManageResults(YsResultDTO dto) {
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        // todo  临时权限
        if (!"ALL".equals(user.getDeptCode())) {
            dto.setDepartmentCode(user.getDeptCode());
        }
        List<YsBudgetResultsVO> result = getManageResult(dto);
        return PageHelperTool.excutePageInfo(result, dto.getNum(), dto.getSize());
    }

    @Override
    public void exportExcelYsManageResults(HttpServletResponse response, YsResultDTO dto) {
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        // todo  临时权限
        if (!"ALL".equals(user.getDeptCode())) {
            dto.setDepartmentCode(user.getDeptCode());
        }
        excelTransfer.exportExcel(response, getManageResult(dto), "部门预算执行结果", "sheet",
                YsBudgetResultsVO.class);
    }

    @Override
    public YsAllYearBudgetBusinessResultsVO listBusinessAllResults(YsResultDTO dto) {
        YsAllYearBudgetBusinessResultsVO vo = new YsAllYearBudgetBusinessResultsVO();
        dto.setAlly(setParam("all_", "_4", 1, 12));
        setDto(dto);
        //  拼接头
        List<YsAllYearBudgetResultsHeadInfoVO> listHead = getListHead();
        vo.setListHead(listHead);

        // 查询出科目对应各个科室的执行率
        Map<String, List<DeptResultData>> finalMap = getAllBusinessYsBudgetResultsVOS(dto);
        List<YsAllYearBudgetResultsDataVO> newVo = getYsAllYearBudgetResultsDataVOS(listHead, finalMap);
        PageInfo<YsAllYearBudgetResultsDataVO> pageInfo = PageHelperTool.excutePageInfo(newVo, dto.getNum(), dto.getSize());
        List<YsAllYearBudgetResultsDataVO> list = pageInfo.getList();

        // 循环newVo，拿到里面的amountVOs循环放到map里
        // map的key为amountVOs下标
        Map<Integer,List<AmountVO>> map = new LinkedHashMap<>();
        newVo.forEach(s->{
            for (int i = 0;i<s.getAmountVOS().size();i++){
                if (!map.containsKey(i)){
                    List<AmountVO> li = new LinkedList<>();
                    li.add(s.getAmountVOS().get(i));
                    map.put(i,li);
                }else{
                    map.get(i).add(s.getAmountVOS().get(i));
                }

            }
        });

        // map循环,map中的value求和就是合计的值
        List<BigDecimal> data = new LinkedList<>();
        List<Integer> flag = new LinkedList<>();
        for (Map.Entry<Integer,List<AmountVO>> entry : map.entrySet()){
            BigDecimal currentAmount = entry.getValue().stream().map(s->s.getCurrentAmount()==null?BigDecimal.ZERO:s.getCurrentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal currentBudget = entry.getValue().stream().map(s->s.getCurrentBudget()==null?BigDecimal.ZERO:s.getCurrentBudget()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalAmount = entry.getValue().stream().map(s->s.getCurrentAmount()==null?BigDecimal.ZERO:s.getCurrentBudget()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalBudget = entry.getValue().stream().map(s->s.getTotalBudget()==null?BigDecimal.ZERO:s.getTotalBudget()).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 当期执行率
            BigDecimal currentRate = currentAmount.divide(currentBudget.compareTo(BigDecimal.ZERO) == 0?BigDecimal.ONE:currentBudget,4, RoundingMode.HALF_UP);
            currentRate = currentRate.multiply(new BigDecimal(100));
            // 全年执行率
            BigDecimal yearRate = totalAmount.divide(totalBudget.compareTo(BigDecimal.ZERO)==0?BigDecimal.ONE:totalBudget,4, RoundingMode.HALF_UP);
            yearRate = yearRate.multiply(new BigDecimal(100));
            data.add(currentRate);
            data.add(yearRate);
            Integer f1;
            if (currentBudget.compareTo(BigDecimal.ZERO) == 0 && currentAmount.compareTo(BigDecimal.ZERO) != 0){
                f1 = 1;
            } else{
                f1 = 0;
            }
            flag.add(f1);

            Integer f2;
            if (totalBudget.compareTo(BigDecimal.ZERO) == 0 && totalAmount.compareTo(BigDecimal.ZERO) != 0){
                f2 = 1;
            } else{
                f2 = 0;
            }
            flag.add(f2);
        }

        // newVO 中求合计数
        YsAllYearBudgetResultsDataVO v = new YsAllYearBudgetResultsDataVO();
        v.setSubjectName("合计");
        v.setData(data);
        v.setFlag(flag);
        list.add(v);
        pageInfo.setList(list);
        vo.setListData(pageInfo);
        return vo;
    }


    @Override
    public void exportExcelYsBusinessAllResults(HttpServletResponse response, YsResultDTO dto) throws IOException {
        List<ExcelVO> list = new ArrayList<>();
        List<YsAllYearBudgetResultsHeadInfoVO> listHead = getListHead();
        Map<String, List<DeptResultData>> finalMap = getAllBusinessYsBudgetResultsVOS(dto);
        List<YsAllYearBudgetResultsDataVO> newVo = getYsAllYearBudgetResultsDataVOS(listHead, finalMap);
        List<List<Object>> dataLists = new ArrayList<>();
        newVo.forEach(k -> {
            List<Object> arrayList = new ArrayList<>();
            arrayList.add(k.getSubjectName());
            for (BigDecimal s : k.getData()) {
                arrayList.add(s);
            }
            dataLists.add(arrayList);
        });
        List<ExcelHead> excelHeads = new ArrayList<>();
        excelHeads.add(ExcelHead.builder()
                .head("预算科目名称")
                .cHead(Collections.singletonList("预算科目名称"))
                .build());
        listHead.forEach(k -> excelHeads.add(ExcelHead.builder()
                .head(k.getDeptName())
                .cHead(Arrays.asList("当期执行率(%)", "全年执行率(%)"))
                .build()));
        List<List<String>> head = getHead(excelHeads);
        list.add(ExcelVO.builder()
                .sheet("sheet")
                .listsHead(head)
                .listsData(dataLists)
                .build());
        excelTransfer.exportExcel(response, "全院业务预算执行结果", list);
    }

    @Override
    public PageInfo<YsAllYearBudgetManageResultsVO> listYsManageAllResults(YsResultDTO dto) {
        List<YsAllYearBudgetManageResultsVO> result = getManageAllResults(dto);
        return PageHelperTool.excutePageInfo(result, dto.getNum(), dto.getSize());

    }

    @Override
    public void exportExcelYsManageAllResults(HttpServletResponse response, YsResultDTO dto) {
        List<YsAllYearBudgetManageResultsVO> result = getManageAllResults(dto);
        excelTransfer2.exportExcel(response, result, "全院管理预算执行结果", "sheet",
                YsAllYearBudgetManageResultsVO.class);
    }

    /**
     * 全院执行结果-业务职能-拼接头
     */
    private List<YsAllYearBudgetResultsHeadInfoVO> getListHead() {
        List<YsDepartment> ysDepartments = baseMapper.listBusinessDepartment();

        List<YsAllYearBudgetResultsHeadInfoVO> listHead = new ArrayList<>();
        ysDepartments.forEach(v -> listHead.add(YsAllYearBudgetResultsHeadInfoVO.builder()
                .deptId(v.getDeptId())
                .deptName(v.getDepartmentName())
                .deptCode(v.getDepartmentCode())
                .monthName("当期执行率(%)")
                .yearName("全年执行率(%)")
                .build()));
        return listHead;
    }

    /**
     * 部门执行结果-业务职能
     */
    private List<YsBudgetResultsVO> getBusinessYsBudgetResultsVOS(YsResultDTO dto) {
        setDto(dto);
        List<YsBudgetResultsVO> resultList = new ArrayList<>();
        // 查询出业务预算科目和部门
        List<SubjectAndDept> subjectAndDeptList = baseMapper.querySubjectAndDept(dto);
        Map<String, List<SubjectAndDept>> subjectMap = subjectAndDeptList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId() + "-" + s.getDeptId()));
        // 预算下达--预算编制发布后数据中获取
        List<SubjectAndDept> orgranizationList = baseMapper.queryOrganizationList(dto);
        Map<String, List<SubjectAndDept>> orgranizationMap = orgranizationList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId() + "-" + s.getDeptId()));
        // 预算执行--预算执行明细中获取
        // 费用类 + 资产类
        // 查询的是三香的
        List<SubjectAndDept> sanList = baseMapper.querySanDetailList(dto);
        // 查询的是浒关的
        List<SubjectAndDept> xuList = baseMapper.queryXuDetailList(dto);
        // 查询全年的三香和浒关的执行数据和
        List<SubjectAndDept> yearList = baseMapper.queryYearList(dto);

        // 合并3个list
        List<SubjectAndDept> totalList = mergeList(sanList, xuList, yearList);
        Map<String, List<SubjectAndDept>> budgetMap = totalList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId() + "-" + s.getDeptId()));

        // 循环map
        for (Map.Entry<String, List<SubjectAndDept>> entry : subjectMap.entrySet()) {
            YsBudgetResultsVO vo = new YsBudgetResultsVO();
            SubjectAndDept sub = entry.getValue().get(0);
            vo.setSubjectId(sub.getSubjectId());
            vo.setSubjectName(sub.getSubjectName());
            vo.setDeptNames(sub.getDeptName());
            // 预算下达
            if (orgranizationMap.get(entry.getKey()) != null) {
                SubjectAndDept org = orgranizationMap.get(entry.getKey()).get(0);
                vo.setXSan(org.getSanCount() == null ? BigDecimal.ZERO : org.getSanCount());
                vo.setXXu(org.getXuCount() == null ? BigDecimal.ZERO : org.getXuCount());
                vo.setXAll(org.getAllCount() == null ? BigDecimal.ZERO : org.getAllCount());
                vo.setSan134(org.getSan134() == null ? BigDecimal.ZERO : org.getSan134());
                vo.setXu134(org.getXu134() == null ? BigDecimal.ZERO : org.getXu134());
                vo.setAll134(org.getAll134() == null ? BigDecimal.ZERO : org.getAll134());
            } else {
                vo.setXSan(BigDecimal.ZERO);
                vo.setXXu(BigDecimal.ZERO);
                vo.setXAll(BigDecimal.ZERO);
                vo.setSan134(BigDecimal.ZERO);
                vo.setXu134(BigDecimal.ZERO);
                vo.setAll134(BigDecimal.ZERO);
            }

            // 预算执行
            if (budgetMap.get(entry.getKey()) != null) {
                SubjectAndDept bud = budgetMap.get(entry.getKey()).get(0);
                vo.setZSan(bud.getSanTotal() == null ? BigDecimal.ZERO : bud.getSanTotal());
                vo.setZXu(bud.getXuTotal() == null ? BigDecimal.ZERO : bud.getXuTotal());
                vo.setZAll(bud.getAllTotal() == null ? BigDecimal.ZERO : bud.getAllTotal());

                // 预算执行率=当期预算执行/当期预算下达
                BigDecimal sanM = vo.getZSan().divide(vo.getXSan().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getXSan(), 4, RoundingMode.HALF_UP);
                vo.setSanM(sanM.multiply(new BigDecimal(100)));
                BigDecimal xuM = vo.getZXu().divide(vo.getXXu().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getXXu(), 4, RoundingMode.HALF_UP);
                vo.setXuM(xuM.multiply(new BigDecimal(100)));
                BigDecimal allM = vo.getZAll().divide(vo.getXAll().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getXAll(), 4, RoundingMode.HALF_UP);
                vo.setAllM(allM.multiply(new BigDecimal(100)));

                if (vo.getXSan().compareTo(BigDecimal.ZERO) == 0 && vo.getZSan().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setSanMFlag(1);
                } else {
                    vo.setSanMFlag(0);
                }

                if (vo.getXXu().compareTo(BigDecimal.ZERO) == 0 && vo.getZXu().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setXuMFlag(1);
                } else {
                    vo.setXuMFlag(0);
                }

                if (vo.getXAll().compareTo(BigDecimal.ZERO) == 0 && vo.getZAll().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setAllMFlag(1);
                } else {
                    vo.setAllMFlag(0);
                }
                // 全年预算执行率=累计预算执行/全年预算下达
                BigDecimal sanY = bud.getSanYear().divide(vo.getSan134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getSan134(), 4, RoundingMode.HALF_UP);
                vo.setSanY(sanY.multiply(new BigDecimal(100)));
                BigDecimal xuY = bud.getXuYear().divide(vo.getXu134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getXu134(), 4, RoundingMode.HALF_UP);
                vo.setXuY(xuY.multiply(new BigDecimal(100)));
                BigDecimal allY = bud.getAllYear().divide(vo.getAll134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : vo.getAll134(), 4, RoundingMode.HALF_UP);
                vo.setAllY(allY.multiply(new BigDecimal(100)));

                if (vo.getSan134().compareTo(BigDecimal.ZERO) == 0 && bud.getSanYear().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setSanYFlag(1);
                } else {
                    vo.setSanYFlag(0);
                }

                if (vo.getXu134().compareTo(BigDecimal.ZERO) == 0 && bud.getXuYear().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setXuYFlag(1);
                } else {
                    vo.setXuYFlag(0);
                }

                if (vo.getAll134().compareTo(BigDecimal.ZERO) == 0 && bud.getAllYear().compareTo(BigDecimal.ZERO) > 0) {
                    vo.setAllYFlag(1);
                } else {
                    vo.setAllYFlag(0);
                }

                // 累计预算执行
                vo.setSanYear(bud.getSanYear());
                vo.setXuYear(bud.getXuYear());
                vo.setAllYear(bud.getAllYear());
            } else {
                vo.setZSan(BigDecimal.ZERO);
                vo.setZXu(BigDecimal.ZERO);
                vo.setZAll(BigDecimal.ZERO);
                vo.setSanM(BigDecimal.ZERO);
                vo.setXuM(BigDecimal.ZERO);
                vo.setAllM(BigDecimal.ZERO);
                vo.setSanY(BigDecimal.ZERO);
                vo.setXuY(BigDecimal.ZERO);
                vo.setAllY(BigDecimal.ZERO);
                vo.setSanYear(BigDecimal.ZERO);
                vo.setXuYear(BigDecimal.ZERO);
                vo.setAllYear(BigDecimal.ZERO);
                vo.setSanMFlag(0);
                vo.setXuMFlag(0);
                vo.setAllMFlag(0);
                vo.setSanYFlag(0);
                vo.setXuYFlag(0);
                vo.setAllYFlag(0);
            }
            resultList.add(vo);
        }
        return resultList;
    }

    /**
     * 预算执行三香，浒关，总年度 合并
     */
    private List<SubjectAndDept> mergeList(List<SubjectAndDept> sanList, List<SubjectAndDept> xuList, List<SubjectAndDept> yearList) {
        List<SubjectAndDept> totalList = new LinkedList<>();
        for (SubjectAndDept subjectAndDept : sanList) {
            SubjectAndDept subjectAndDept1 = xuList.stream().filter(s -> s.getSubjectId() != null && s.getSubjectId().equals(subjectAndDept.getSubjectId()) && s.getDeptId() != null && s.getDeptId().equals(subjectAndDept.getDeptId())).findFirst().orElse(null);
            if (subjectAndDept1 == null) {
                subjectAndDept.setXuTotal(BigDecimal.ZERO);
                subjectAndDept.setAllTotal(subjectAndDept.getSanTotal() == null ? BigDecimal.ZERO : subjectAndDept.getSanTotal());
            } else {
                subjectAndDept.setXuTotal(subjectAndDept1.getXuTotal());
                subjectAndDept.setAllTotal((subjectAndDept.getSanTotal() == null ? BigDecimal.ZERO : subjectAndDept.getSanTotal()).add(subjectAndDept.getXuTotal() == null ? BigDecimal.ZERO : subjectAndDept.getXuTotal()));
            }
            SubjectAndDept subjectAndDept2 = yearList.stream().filter(s -> s.getSubjectId() != null && s.getSubjectId().equals(subjectAndDept.getSubjectId()) && s.getDeptId() != null && s.getDeptId().equals(subjectAndDept.getDeptId())).findFirst().orElse(null);
            if (subjectAndDept2 == null) {
                subjectAndDept.setSanYear(BigDecimal.ZERO);
                subjectAndDept.setXuYear(BigDecimal.ZERO);
                subjectAndDept.setAllYear(BigDecimal.ZERO);
            } else {
                subjectAndDept.setSanYear(subjectAndDept2.getSanYear() == null ? BigDecimal.ZERO : subjectAndDept2.getSanYear());
                subjectAndDept.setXuYear(subjectAndDept2.getXuYear() == null ? BigDecimal.ZERO : subjectAndDept2.getXuYear());
                subjectAndDept.setAllYear((subjectAndDept2.getSanYear() == null ? BigDecimal.ZERO : subjectAndDept2.getSanYear()).add(subjectAndDept2.getXuYear() == null ? BigDecimal.ZERO : subjectAndDept2.getXuYear()));
            }
            totalList.add(subjectAndDept);
        }
        return totalList;
    }

    /**
     * 全院执行结果-业务职能1
     */
    private Map<String, List<DeptResultData>> getAllBusinessYsBudgetResultsVOS(YsResultDTO dto) {
        setDto(dto);
        // 查询出业务预算科目和部门
        List<SubjectAndDept> subjectAndDeptList = baseMapper.querySubjectAndDept(dto);
        Map<String, List<SubjectAndDept>> subjectMap = subjectAndDeptList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId() + "-" + s.getDeptId()));
        // 预算下达--预算编制发布后数据中获取
        List<SubjectAndDept> orgranizationList = baseMapper.queryOrganizationList(dto);
        Map<Integer, List<SubjectAndDept>> orgranizationMap = orgranizationList.stream().collect(Collectors.groupingBy(SubjectAndDept::getSubjectId));
        // 预算执行--预算执行明细中获取
        // 费用类 + 资产类
        // 查询的是三香的
        List<SubjectAndDept> sanList = baseMapper.querySanDetailList(dto);
        // 查询的是浒关的
        List<SubjectAndDept> xuList = baseMapper.queryXuDetailList(dto);
        // 查询全年的三香和浒关的执行数据和
        List<SubjectAndDept> yearList = baseMapper.queryYearList(dto);

        // 合并3个list
        List<SubjectAndDept> totalList = mergeList(sanList, xuList, yearList);
        Map<Integer, List<SubjectAndDept>> budgetMap = totalList.stream().collect(Collectors.groupingBy(SubjectAndDept::getSubjectId));

        // 循环map--拿出对应的subjectId和deptId
        Map<String, List<DeptResultData>> finalMap = new HashMap<>();
        for (Map.Entry<String, List<SubjectAndDept>> entry : subjectMap.entrySet()) {
            SubjectAndDept sub = entry.getValue().get(0);
            // 预算下达的list：key：subjectId-deptId，value：
            List<SubjectAndDept> orgList = orgranizationMap.get(sub.getSubjectId());
            // 预算执行的List：
            List<SubjectAndDept> sdtList = budgetMap.get(sub.getSubjectId());
            Map<String, List<SubjectAndDept>> orgMap = new HashMap<>();
            Map<String, List<SubjectAndDept>> sdtMap = new HashMap<>();
            if (orgList != null) {
                orgList = orgList.stream().filter(s -> s.getDeptId() != null).collect(Collectors.toList());
                orgMap = orgList.stream().collect(Collectors.groupingBy(SubjectAndDept::getDeptId));
            } else {
                // 如果没有该预算科目的下达数据的时候，构建一条空数据
                List<SubjectAndDept> list = new ArrayList<>();
                SubjectAndDept i = new SubjectAndDept();
                i.setDeptId("N");
                i.setAllCount(BigDecimal.ZERO);
                i.setAll134(BigDecimal.ZERO);
                i.setSubjectName(sub.getSubjectName());
                i.setSubjectId(sub.getSubjectId());
                list.add(i);
                orgMap.put("N", list);
            }
            if (sdtList != null) {
                sdtList = sdtList.stream().filter(s -> s.getDeptId() != null).collect(Collectors.toList());
                sdtMap = sdtList.stream().collect(Collectors.groupingBy(SubjectAndDept::getDeptId));
            } else {
                List<SubjectAndDept> list = new ArrayList<>();
                SubjectAndDept i = new SubjectAndDept();
                i.setDeptId("N");
                i.setAllTotal(BigDecimal.ZERO);
                i.setAllYear(BigDecimal.ZERO);
                i.setSubjectName(sub.getSubjectName());
                i.setSubjectId(sub.getSubjectId());
                list.add(i);
                sdtMap.put("N", list);
            }

            List<DeptResultData> deptList = new ArrayList<>();
            for (Map.Entry<String, List<SubjectAndDept>> m : orgMap.entrySet()) {
                DeptResultData data = new DeptResultData();
                data.setDeptId(m.getKey());
                if (sdtMap.get(m.getKey()) != null) {
                    SubjectAndDept s = sdtMap.get(m.getKey()).get(0);
                    SubjectAndDept m1 = m.getValue().get(0);
                    BigDecimal currentRate = s.getAllTotal().divide(m1.getAllCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : m1.getAllCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal yearRate = s.getAllYear().divide(m1.getAll134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : m1.getAll134(), 4, RoundingMode.HALF_UP);
                    data.setCurrentAmount(s.getAllTotal());
                    data.setCurrentBudget(m1.getAllCount());
                    data.setTotalBudget(m1.getAll134());
                    data.setTotalAmount(s.getAllYear());
                    data.setCurrentRate(currentRate.multiply(new BigDecimal(100)));
                    if (m1.getAllCount().compareTo(BigDecimal.ZERO) == 0 && s.getAllTotal().compareTo(BigDecimal.ZERO) > 0) {
                        data.setCurrentRateFlag(1);
                    } else {
                        data.setCurrentRateFlag(0);
                    }
                    data.setYearRate(yearRate.multiply(new BigDecimal(100)));
                    if (m1.getAll134().compareTo(BigDecimal.ZERO) == 0 && s.getAllYear().compareTo(BigDecimal.ZERO) > 0) {
                        data.setYearRateFlag(1);
                    } else {
                        data.setYearRateFlag(0);
                    }
                } else {

                    data.setCurrentAmount(BigDecimal.ZERO);
                    data.setCurrentBudget(BigDecimal.ZERO);
                    data.setTotalBudget(BigDecimal.ZERO);
                    data.setTotalAmount(BigDecimal.ZERO);

                    data.setCurrentRate(BigDecimal.ZERO);
                    data.setCurrentRateFlag(0);
                    data.setYearRate(BigDecimal.ZERO);
                    data.setYearRateFlag(0);

                }
                deptList.add(data);
            }
            for (Map.Entry<String, List<SubjectAndDept>> s : sdtMap.entrySet()) {
                DeptResultData data = new DeptResultData();
                data.setDeptId(s.getKey());
                if (orgMap.get(s.getKey()) != null) {
                    SubjectAndDept m = orgMap.get(s.getKey()).get(0);
                    SubjectAndDept s1 = s.getValue().get(0);
                    BigDecimal currentRate = s1.getAllTotal().divide(m.getAllCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : m.getAllCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal yearRate = s1.getAllYear().divide(m.getAll134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : m.getAll134(), 4, RoundingMode.HALF_UP);
                    data.setCurrentAmount(s1.getAllTotal());
                    data.setCurrentBudget(m.getAllCount());
                    data.setTotalAmount(s1.getAllYear());
                    data.setTotalBudget(m.getAll134());
                    data.setCurrentRate(currentRate.multiply(new BigDecimal(100)));

                    if (m.getAllCount().compareTo(BigDecimal.ZERO) == 0 && s1.getAllTotal().compareTo(BigDecimal.ZERO) != 0) {
                        data.setCurrentRateFlag(1);
                    } else {
                        data.setCurrentRateFlag(0);
                    }
                    data.setYearRate(yearRate.multiply(new BigDecimal(100)));
                    if (m.getAll134().compareTo(BigDecimal.ZERO) == 0 && s1.getAllYear().compareTo(BigDecimal.ZERO) != 0) {
                        data.setYearRateFlag(1);
                    } else {
                        data.setYearRateFlag(0);
                    }
                } else {
                    data.setCurrentAmount(BigDecimal.ZERO);
                    data.setCurrentBudget(BigDecimal.ZERO);
                    data.setTotalBudget(BigDecimal.ZERO);
                    data.setTotalAmount(BigDecimal.ZERO);

                    data.setCurrentRate(BigDecimal.ZERO);
                    data.setYearRate(BigDecimal.ZERO);
                    data.setCurrentRateFlag(0);
                    data.setYearRateFlag(0);
                }
                deptList.add(data);
            }
            deptList = deptList.stream().distinct().collect(Collectors.toList());
            finalMap.put(sub.getSubjectName(), deptList);
        }
        return finalMap;
    }

    /**
     * 全院执行结果-业务职能2
     */
    private List<YsAllYearBudgetResultsDataVO> getYsAllYearBudgetResultsDataVOS(List<YsAllYearBudgetResultsHeadInfoVO> listHead, Map<String, List<DeptResultData>> finalMap) {
        List<YsAllYearBudgetResultsDataVO> newVo = new ArrayList<>();

        for (Map.Entry<String, List<DeptResultData>> map : finalMap.entrySet()) {
            YsAllYearBudgetResultsDataVO resultVo = new YsAllYearBudgetResultsDataVO();
            resultVo.setSubjectName(map.getKey());
            List<BigDecimal> value = new LinkedList<>();
            List<Integer> flag = new LinkedList<>();
            List<AmountVO> amountVOS = new LinkedList<>();
            for (YsAllYearBudgetResultsHeadInfoVO head : listHead) {
                if (map.getValue().size() == 1 && "N".equals(map.getValue().get(0).getDeptId())) {
                    AmountVO amount = new AmountVO();
                    // 当期执行率
                    value.add(BigDecimal.ZERO);
                    flag.add(0);
                    // 全年执行率
                    value.add(BigDecimal.ZERO);
                    flag.add(0);

                    amount.setCurrentAmount(BigDecimal.ZERO);
                    amount.setCurrentBudget(BigDecimal.ZERO);
                    amount.setTotalAmount(BigDecimal.ZERO);
                    amount.setTotalBudget(BigDecimal.ZERO);
                    amountVOS.add(amount);
                }
                map.getValue().forEach(x -> {
                    if (x.getDeptId() != null && x.getDeptId().equals(head.getDeptId())) {
                        AmountVO amount = new AmountVO();
                        // 当期执行率
                        value.add(x.getCurrentRate());
                        if (x.getCurrentBudget().compareTo(BigDecimal.ZERO) == 0 && x.getCurrentAmount().compareTo(BigDecimal.ZERO) != 0){
                            flag.add(1);
                        } else {
                            flag.add(0);
                        }
                        // 全年执行率
                        value.add(x.getYearRate());
                        if (x.getTotalBudget().compareTo(BigDecimal.ZERO) == 0 && x.getTotalAmount().compareTo(BigDecimal.ZERO) != 0){
                            flag.add(1);
                        } else {
                            flag.add(0);
                        }
                        amount.setCurrentAmount(x.getCurrentAmount());
                        amount.setCurrentBudget(x.getCurrentBudget());
                        amount.setTotalAmount(x.getTotalAmount());
                        amount.setTotalBudget(x.getTotalBudget());
                        amountVOS.add(amount);
                    }
                });
            }
            resultVo.setData(value);
            resultVo.setFlag(flag);
            resultVo.setAmountVOS(amountVOS);
            newVo.add(resultVo);
        }
        return newVo;
    }

    /**
     * 全院执行结果-管理职能
     */
    private List<YsAllYearBudgetManageResultsVO> getManageAllResults(YsResultDTO dto) {
        List<YsAllYearBudgetManageResultsVO> resultlist = new ArrayList<>();
        setDto(dto);
        // 查询出属于管理职能的预算科目和对应的部门和类型
        List<SubjectAndDept> list = baseMapper.selectManageSubjects(dto);
        Map<Integer, List<SubjectAndDept>> subjectMap = list.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        List<SubjectAndDept> newList = new ArrayList<>();
        for (Map.Entry<Integer, List<SubjectAndDept>> map : subjectMap.entrySet()) {
            List<SubjectAndDept> subjectAndDepts = subjectMap.get(map.getKey());
            SubjectAndDept sub = new SubjectAndDept();
            BeanUtils.copyProperties(subjectAndDepts.get(0), sub);
            List<String> deptIds = subjectAndDepts.stream().map(SubjectAndDept::getDeptId).collect(Collectors.toList());
            List<String> deptCodes = subjectAndDepts.stream().map(SubjectAndDept::getDeptCode).collect(Collectors.toList());
            List<String> deptNames = subjectAndDepts.stream().map(SubjectAndDept::getDeptName).collect(Collectors.toList());
            String deptId = String.join(",", deptIds);
            String deptCode = String.join(",", deptCodes);
            String deptName = String.join(",", deptNames);
            sub.setDeptId(deptId);
            sub.setDeptCode(deptCode);
            sub.setDeptName(deptName);
            newList.add(sub);
        }
        Map<Integer, List<SubjectAndDept>> newSubjectMap = newList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        // 从预算下达表中查询预算下达，查询累计月的预算下达和全年的预算下达
        List<SubjectAndDept> listX = baseMapper.selectManageResultData(dto);
        Map<Integer, List<SubjectAndDept>> xMap = listX.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        // 从预算执行明细中查询区间累计月预算执行
        // 查询的是三香的
        List<SubjectAndDept> sanList = baseMapper.queryManageSanDetailList(dto);
        // 查询的是浒关的
        List<SubjectAndDept> xuList = baseMapper.queryManageXuDetailList(dto);
        // 查询全年的三香和浒关的执行数据和
        List<SubjectAndDept> yearList = baseMapper.queryManageYearList(dto);
        // 合并3个list
        List<SubjectAndDept> totalList = mergeList(sanList, xuList, yearList);
        Map<Integer, List<SubjectAndDept>> zMap = totalList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        for (Map.Entry<Integer, List<SubjectAndDept>> map : newSubjectMap.entrySet()) {
            YsAllYearBudgetManageResultsVO vo = new YsAllYearBudgetManageResultsVO();
            SubjectAndDept subject = map.getValue().get(0);
            vo.setSubjectName(subject.getSubjectName());
            vo.setDeptNames(subject.getDeptName());
            vo.setCategory(subject.getManageType());
            // 预算下达
            if (xMap.containsKey(map.getKey()) && zMap.containsKey(map.getKey())) {
                SubjectAndDept x = xMap.get(map.getKey()).get(0);
                SubjectAndDept z = zMap.get(map.getKey()).get(0);

                if (x != null) {
                    // 预算下达数据
                    vo.setXSan(x.getSanCount());
                    vo.setXXu(x.getXuCount());
                    vo.setXAll(x.getAllCount());
                } else {
                    vo.setXSan(BigDecimal.ZERO);
                    vo.setXXu(BigDecimal.ZERO);
                    vo.setXAll(BigDecimal.ZERO);
                }
                if (z != null) {
                    vo.setZSan(z.getSanTotal());
                    vo.setZXu(z.getXuTotal());
                    vo.setZAll(z.getAllTotal());
                } else {
                    vo.setZSan(BigDecimal.ZERO);
                    vo.setZXu(BigDecimal.ZERO);
                    vo.setZAll(BigDecimal.ZERO);
                }

                if (x == null || z == null) {
                    vo.setSanM(BigDecimal.ZERO);
                    vo.setXuM(BigDecimal.ZERO);
                    vo.setAllM(BigDecimal.ZERO);
                } else {
                    // 当期执行率 = 当期预算执行/当期预算下达
                    BigDecimal sanM = z.getSanTotal().divide(x.getSanCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getSanCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal xuM = z.getXuTotal().divide(x.getXuCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getXuCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal allM = z.getAllTotal().divide(x.getAllCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getAllCount(), 4, RoundingMode.HALF_UP);
                    vo.setSanM(sanM.multiply(new BigDecimal(100)));
                    vo.setXuM(xuM.multiply(new BigDecimal(100)));
                    vo.setAllM(allM.multiply(new BigDecimal(100)));
                    if (x.getSanCount().compareTo(BigDecimal.ZERO) == 0 && z.getSanTotal().compareTo(BigDecimal.ZERO) != 0) {
                        vo.setSanMFlag(1);
                    } else {
                        vo.setSanMFlag(0);
                    }
                    if (x.getXuCount().compareTo(BigDecimal.ZERO) == 0 && z.getXuTotal().compareTo(BigDecimal.ZERO) != 0) {
                        vo.setXuMFlag(1);
                    } else {
                        vo.setXuMFlag(0);
                    }
                    if (x.getAllCount().compareTo(BigDecimal.ZERO) == 0 && z.getAllTotal().compareTo(BigDecimal.ZERO) != 0) {
                        vo.setAllMFlag(1);
                    } else {
                        vo.setAllMFlag(0);
                    }
                }
            } else {
                vo.setXSan(BigDecimal.ZERO);
                vo.setXXu(BigDecimal.ZERO);
                vo.setXAll(BigDecimal.ZERO);
                vo.setZSan(BigDecimal.ZERO);
                vo.setZXu(BigDecimal.ZERO);
                vo.setZAll(BigDecimal.ZERO);
                vo.setZSan(BigDecimal.ZERO);
                vo.setZXu(BigDecimal.ZERO);
                vo.setZAll(BigDecimal.ZERO);
                vo.setSanM(BigDecimal.ZERO);
                vo.setXuM(BigDecimal.ZERO);
                vo.setAllM(BigDecimal.ZERO);
                vo.setSanMFlag(0);
                vo.setXuMFlag(0);
                vo.setAllMFlag(0);
            }
            resultlist.add(vo);
        }
        // 排序
        List<YsAllYearBudgetManageResultsVO> result = new ArrayList<>();
        List<YsAllYearBudgetManageResultsVO> list1 = resultlist.stream().filter(t -> "费用类".equals(t.getCategory())).collect(Collectors.toList());
        List<YsAllYearBudgetManageResultsVO> list2 = resultlist.stream().filter(t -> "资本类".equals(t.getCategory())).collect(Collectors.toList());
        List<YsAllYearBudgetManageResultsVO> list3 = resultlist.stream().filter(t -> "药品".equals(t.getCategory())).collect(Collectors.toList());
        List<YsAllYearBudgetManageResultsVO> list4 = resultlist.stream().filter(t -> "耗材".equals(t.getCategory())).collect(Collectors.toList());
        result.addAll(list1);
        result.addAll(list2);
        result.addAll(list3);
        result.addAll(list4);
        return result;
    }

    /**
     * 管理部门执行结果-管理职能
     */
    private List<YsBudgetResultsVO> getManageResult(YsResultDTO dto) {
        List<YsBudgetResultsVO> resultlist = new ArrayList<>();
        setDto(dto);
        // 查询出属于管理职能的预算科目和对应的部门和类型
        List<SubjectAndDept> list = baseMapper.selectManageSubjects(dto);
        Map<Integer, List<SubjectAndDept>> subjectMap = list.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        List<SubjectAndDept> newList = new ArrayList<>();
        for (Map.Entry<Integer, List<SubjectAndDept>> map : subjectMap.entrySet()) {
            List<SubjectAndDept> subjectAndDepts = subjectMap.get(map.getKey());
            SubjectAndDept sub = new SubjectAndDept();
            BeanUtils.copyProperties(subjectAndDepts.get(0), sub);
            List<String> deptIds = subjectAndDepts.stream().map(SubjectAndDept::getDeptId).collect(Collectors.toList());
            List<String> deptCodes = subjectAndDepts.stream().map(SubjectAndDept::getDeptCode).collect(Collectors.toList());
            List<String> deptNames = subjectAndDepts.stream().map(SubjectAndDept::getDeptName).collect(Collectors.toList());
            String deptId = String.join(",", deptIds);
            String deptCode = String.join(",", deptCodes);
            String deptName = String.join(",", deptNames);
            sub.setDeptId(deptId);
            sub.setDeptCode(deptCode);
            sub.setDeptName(deptName);
            newList.add(sub);
        }
        Map<Integer, List<SubjectAndDept>> newSubjectMap = newList.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        // 从预算下达表中查询预算下达，查询累计月的预算下达和全年的预算下达
        List<SubjectAndDept> listX = baseMapper.selectManageResultData(dto);
        Map<Integer, List<SubjectAndDept>> xMap = listX.stream().collect(Collectors.groupingBy(s -> s.getSubjectId()));

        // 从预算执行明细中查询区间累计月预算执行
        // 查询的是三香的
        List<SubjectAndDept> sanList = baseMapper.queryManageSanDetailList(dto);
        // 查询的是浒关的
        List<SubjectAndDept> xuList = baseMapper.queryManageXuDetailList(dto);
        // 查询全年的三香和浒关的执行数据和
        List<SubjectAndDept> yearList = baseMapper.queryManageYearList(dto);
        // 合并3个list
        List<SubjectAndDept> totalList = mergeList(sanList, xuList, yearList);
        Map<Integer, List<SubjectAndDept>> zMap = totalList.stream().filter(s->s.getSubjectId()!=null).collect(Collectors.groupingBy(s -> s.getSubjectId()));

        for (Map.Entry<Integer, List<SubjectAndDept>> map : newSubjectMap.entrySet()) {
            YsBudgetResultsVO vo = new YsBudgetResultsVO();
            SubjectAndDept subject = map.getValue().get(0);
            vo.setSubjectId(map.getKey());
            vo.setSubjectName(subject.getSubjectName());
            vo.setDeptIds(subject.getDeptId());
            vo.setDeptNames(subject.getDeptName());
            vo.setCategory(subject.getManageType());
            vo.setCategoryId(subject.getCategoryId());
            // 预算下达
            if (xMap.containsKey(map.getKey()) || zMap.containsKey(map.getKey())) {
                SubjectAndDept x = xMap.get(map.getKey()) == null ? null : xMap.get(map.getKey()).get(0);
                SubjectAndDept z = zMap.get(map.getKey()) == null ? null : zMap.get(map.getKey()).get(0);

                if (x != null) {
                    // 预算下达数据
                    vo.setXSan(x.getSanCount());
                    vo.setXXu(x.getXuCount());
                    vo.setXAll(x.getAllCount());
                } else {
                    vo.setXSan(BigDecimal.ZERO);
                    vo.setXXu(BigDecimal.ZERO);
                    vo.setXAll(BigDecimal.ZERO);
                }
                if (z != null) {
                    vo.setZSan(z.getSanTotal());
                    vo.setZXu(z.getXuTotal());
                    vo.setZAll(z.getAllTotal());
                } else {
                    vo.setZSan(BigDecimal.ZERO);
                    vo.setZXu(BigDecimal.ZERO);
                    vo.setZAll(BigDecimal.ZERO);
                }

                if (x == null || z == null) {
                    vo.setSanM(BigDecimal.ZERO);
                    vo.setXuM(BigDecimal.ZERO);
                    vo.setAllM(BigDecimal.ZERO);
                } else {
                    // 当期执行率 = 当期预算执行/当期预算下达
                    BigDecimal sanM = z.getSanTotal().divide(x.getSanCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getSanCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal xuM = z.getXuTotal().divide(x.getXuCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getXuCount(), 4, RoundingMode.HALF_UP);
                    BigDecimal allM = z.getAllTotal().divide(x.getAllCount().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getAllCount(), 4, RoundingMode.HALF_UP);
                    vo.setSanM(sanM.multiply(new BigDecimal(100)));
                    vo.setXuM(xuM.multiply(new BigDecimal(100)));
                    vo.setAllM(allM.multiply(new BigDecimal(100)));

                    if (x.getSanCount().compareTo(BigDecimal.ZERO) == 0 && z.getSanTotal().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setSanMFlag(1);
                    } else {
                        vo.setSanMFlag(0);
                    }

                    if (x.getAllCount().compareTo(BigDecimal.ZERO) == 0 && z.getXuTotal().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setXuMFlag(1);
                    } else {
                        vo.setXuMFlag(0);
                    }

                    if (x.getAllCount().compareTo(BigDecimal.ZERO) == 0 && z.getAllTotal().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setAllMFlag(1);
                    } else {
                        vo.setAllMFlag(0);
                    }

                    // 全年预算执行率=累计预算执行/全年预算下达
                    BigDecimal sanY = z.getSanYear().divide(x.getSan134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getSan134(), 4, RoundingMode.HALF_UP);
                    BigDecimal xuY = z.getXuYear().divide(x.getXu134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getXu134(), 4, RoundingMode.HALF_UP);
                    BigDecimal allY = z.getAllYear().divide(x.getAll134().compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : x.getAll134(), 4, RoundingMode.HALF_UP);
                    vo.setSanY(sanY.multiply(new BigDecimal(100)));
                    vo.setXuY(xuY.multiply(new BigDecimal(100)));
                    vo.setAllY(allY.multiply(new BigDecimal(100)));

                    if (x.getSan134().compareTo(BigDecimal.ZERO) == 0 && z.getSanYear().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setSanYFlag(1);
                    } else {
                        vo.setSanYFlag(0);
                    }

                    if (x.getXu134().compareTo(BigDecimal.ZERO) == 0 && z.getXuYear().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setXuYFlag(1);
                    } else {
                        vo.setXuYFlag(0);
                    }

                    if (x.getAll134().compareTo(BigDecimal.ZERO) == 0 && z.getAllYear().compareTo(BigDecimal.ZERO) > 0) {
                        vo.setAllYFlag(1);
                    } else {
                        vo.setAllYFlag(0);
                    }
                }
            } else {
                vo.setXSan(BigDecimal.ZERO);
                vo.setXXu(BigDecimal.ZERO);
                vo.setXAll(BigDecimal.ZERO);
                vo.setZSan(BigDecimal.ZERO);
                vo.setZXu(BigDecimal.ZERO);
                vo.setZAll(BigDecimal.ZERO);
                vo.setZSan(BigDecimal.ZERO);
                vo.setZXu(BigDecimal.ZERO);
                vo.setZAll(BigDecimal.ZERO);
                vo.setSanM(BigDecimal.ZERO);
                vo.setXuM(BigDecimal.ZERO);
                vo.setAllM(BigDecimal.ZERO);
                vo.setSanY(BigDecimal.ZERO);
                vo.setXuY(BigDecimal.ZERO);
                vo.setAllY(BigDecimal.ZERO);
                vo.setSanMFlag(0);
                vo.setXuMFlag(0);
                vo.setAllMFlag(0);
                vo.setSanYFlag(0);
                vo.setXuYFlag(0);
                vo.setAllYFlag(0);
            }
            resultlist.add(vo);
        }
        // 排序
        List<YsBudgetResultsVO> result = new ArrayList<>();
        List<YsBudgetResultsVO> list1 = resultlist.stream().filter(t -> "费用类".equals(t.getCategory())).collect(Collectors.toList());
        List<YsBudgetResultsVO> list2 = resultlist.stream().filter(t -> "资本类".equals(t.getCategory())).collect(Collectors.toList());
        List<YsBudgetResultsVO> list3 = resultlist.stream().filter(t -> "药品".equals(t.getCategory())).collect(Collectors.toList());
        List<YsBudgetResultsVO> list4 = resultlist.stream().filter(t -> "耗材".equals(t.getCategory())).collect(Collectors.toList());
        result.addAll(setRate(list1));
        result.addAll(setRate(list2));
        result.addAll(setRate(list3));
        result.addAll(setRate(list4));
        return result;
    }

    private List<YsBudgetResultsVO> setRate(List<YsBudgetResultsVO> list) {
        BigDecimal fzSanTotal = list.stream().map(YsBudgetResultsVO::getZSan).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fxSanTotal = list.stream().map(YsBudgetResultsVO::getXSan).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fSanRate = fzSanTotal.divide(fxSanTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : fxSanTotal, 4, RoundingMode.HALF_UP);
        BigDecimal fzXuTotal = list.stream().map(YsBudgetResultsVO::getZXu).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fxXuTotal = list.stream().map(YsBudgetResultsVO::getXXu).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fXuRate = fzXuTotal.divide(fxXuTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : fxXuTotal, 4, RoundingMode.HALF_UP);
        BigDecimal fzAllTotal = list.stream().map(YsBudgetResultsVO::getZAll).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fxAllTotal = list.stream().map(YsBudgetResultsVO::getXAll).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fAllRate = fzAllTotal.divide(fxAllTotal.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ONE : fxAllTotal, 4, RoundingMode.HALF_UP);
        list.forEach(s -> {
            s.setSanTotalRate(fSanRate.multiply(new BigDecimal(100)));
            s.setXuTotalRate(fXuRate.multiply(new BigDecimal(100)));
            s.setAllTotalRate(fAllRate.multiply(new BigDecimal(100)));
            if (fxSanTotal.compareTo(BigDecimal.ZERO) == 0 && fzSanTotal.compareTo(BigDecimal.ZERO) > 0){
                s.setSanTotalRateFlag(1);
            }else{
                s.setSanTotalRateFlag(0);
            }
            if (fxXuTotal.compareTo(BigDecimal.ZERO) == 0 && fzXuTotal.compareTo(BigDecimal.ZERO) > 0){
                s.setXuTotalRateFlag(1);
            }else{
                s.setXuTotalRateFlag(0);
            }
            if (fxAllTotal.compareTo(BigDecimal.ZERO) == 0 && fzAllTotal.compareTo(BigDecimal.ZERO) > 0){
                s.setAllTotalRateFlag(1);
            }else{
                s.setAllTotalRateFlag(0);
            }
        });
        return list;
    }

    private List<List<String>> getHead(List<ExcelHead> headList) {
        List<List<String>> lists = new ArrayList<>();
        headList.forEach(e -> e.getCHead()
                .forEach(c -> {
                    List<String> list = new ArrayList<>();
                    list.add(e.getHead());
                    String[] split = Optional.ofNullable(c)
                            .orElse("")
                            .split(",");
                    String s = split.length > 1 ? split[1] : c;
                    list.add(s);
                    lists.add(list);
                }));
        return lists;
    }

    private String setDto(YsResultDTO dto) {
        Optional.ofNullable(dto.getStartTime())
                .orElseThrow(() -> new RuntimeException("起始时间不能为空"));
        Optional.ofNullable(dto.getEndTime())
                .orElseThrow(() -> new RuntimeException("截止时间不能为空"));
        YearMonth startTime = dto.getStartTime();
        int year = startTime.getYear();
        dto.setYear(String.valueOf(year));
        int startMonth = startTime.getMonth()
                .getValue();
        int endMonth = dto.getEndTime()
                .getMonth()
                .getValue();
        dto.setDbStartTime(LocalDateTime.of(year, startMonth, 1, 0, 0, 0));
        dto.setDbEndTime(LocalDateTime.of(year, endMonth , dto.getEndTime().lengthOfMonth(), 23, 59, 59));
        dto.setSan(setParam("san_", "_4", startMonth, endMonth));
        dto.setXu(setParam("xu_", "_4", startMonth, endMonth));
        dto.setAll(setParam("all_", "_4", startMonth, endMonth));
        if (startMonth < 10) {
            dto.setStart(Integer.valueOf(year + "0" + startMonth));
        } else {
            dto.setStart(Integer.valueOf(year + String.valueOf(startMonth)));
        }
        if (endMonth < 10) {
            dto.setEnd(Integer.valueOf(year + "0" + endMonth));
        } else {
            dto.setEnd(Integer.valueOf(year + String.valueOf(endMonth)));
        }
        return startMonth + "月到" + endMonth + "月执行率";
    }

    public String setParam(String startString, String endString, int startInt, int endInt) {
        StringBuilder builder = new StringBuilder();
        for (int i = startInt; i < endInt + 1; i++) {
            builder.append("isnull(").append(startString)
                    .append(i)
                    .append(endString).append(",0)");
            if (i == endInt) {
                return builder.toString();
            }
            builder.append("+");
        }
        return null;
    }
}
